package com.chen.ui;

import com.chen.cache.PrivateMessageCache;
import com.chen.entry.PrivateMessage;
import com.chen.infa.ChatMessageListener;
import com.chen.infa.ChatUpdateUserListListener;
import com.chen.infa.PrivateChatMessageListener;
import com.chen.runnabletask.ClientThread;
import com.chen.util.AppContext;
import com.chen.util.Constant;

import javax.swing.*;
import java.awt.*;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Objects;

public class ChatGUI extends JFrame {

    private JTextArea chatArea;
    private JTextField inputField;
    private JList<String> userList;
    private DefaultListModel<String> userModel;
    private PrivateChatWindow privateChatPanel;

    public ChatGUI() {
        initView();
        setVisible(true);
        initUserList(AppContext.getInstance().getUsername());
    }

    public void initUserList(String userName) {
        setTitle(userName + "的聊天界面");
        // 客户也需要一个子线程来处理用户列表更新和群消息更新，
        ClientThread clientThread = ClientThread.getInstance();
        // 创建用户列表更新监听器
        ChatUpdateUserListListener chatUpdateUserListListener = (users) -> SwingUtilities.invokeLater(() -> {
            this.updateOnLineUserList(users);
        });
        // 创建群聊消息接收监听器
        ChatMessageListener chatMessageListener = (message) -> SwingUtilities.invokeLater(() -> {
            this.showMsgToAll(message);
        });
        // 创建私聊消息接收监听器
        PrivateChatMessageListener privateChatMessageListener = (fromUser, toUser, content) -> SwingUtilities.invokeLater(() -> {
            if (Objects.nonNull(privateChatPanel)) {
                this.onServerMessageReceived(fromUser, toUser, content);
            }
        });
        // 将监听器传入网络监听线程
        clientThread.setChatUpdateUserListListener(chatUpdateUserListListener);
        clientThread.setChatMessageListener(chatMessageListener);
        clientThread.setPrivateChatMessageListener(privateChatMessageListener);
        // 调式的时候遇到个问题，就是监听器在线程里都是null
        // 最后发现，监听器的注册，需要在线程启动之前
        new Thread(clientThread).start();
    }

    private void initView() {
        setSize(700, 500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null); // 居中显示
        setLayout(new BorderLayout());

        // ====== 左侧面板 - 用户列表 ======
        userModel = new DefaultListModel<>();

        userList = new JList<>(userModel);
        userList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JScrollPane userScrollPane = new JScrollPane(userList);
        userScrollPane.setBorder(BorderFactory.createTitledBorder("在线用户"));

        JPanel leftPanel = new JPanel(new BorderLayout());
        leftPanel.setPreferredSize(new Dimension(150, getHeight()));
        leftPanel.add(userScrollPane, BorderLayout.CENTER);

        // ====== 右侧主面板 ======
        JPanel rightPanel = new JPanel(new BorderLayout());

        // 聊天显示区域
        chatArea = new JTextArea();
        chatArea.setEditable(false);
        //chatArea.setBackground(new Color(211, 211, 211));
        JScrollPane chatScrollPane = new JScrollPane(chatArea);
        chatScrollPane.setBorder(BorderFactory.createTitledBorder("聊天记录"));
        rightPanel.add(chatScrollPane, BorderLayout.CENTER);

        // 输入框和按钮
        JPanel inputPanel = new JPanel(new BorderLayout());

        inputField = new JTextField();
        inputField.addActionListener(e -> sendMessage());

        JButton sendButton = new JButton("发送");
        JButton privateButton = new JButton("私聊");

        sendButton.addActionListener(e -> sendMessage());
        privateButton.addActionListener(e -> openPrivateChatWindow());

        inputPanel.add(inputField, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.add(privateButton);
        buttonPanel.add(sendButton);

        inputPanel.add(buttonPanel, BorderLayout.EAST);

        rightPanel.add(inputPanel, BorderLayout.SOUTH);

        // ====== 整体布局组合 ======
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, rightPanel);
        splitPane.setDividerLocation(160);
        add(splitPane, BorderLayout.CENTER);
    }

    // 发送消息方法
    private void sendMessage() {
        try {
            // 获取画面输入框内容
            String message = inputField.getText().trim();
            inputField.setText("");

            // 获取管道的输出流
            DataOutputStream out = new DataOutputStream(AppContext.getInstance().getClientSocket().getOutputStream());
            if (!message.isEmpty()) {
                // 这里出现了一个错误，因为准备发送的消息没有提前设置
                out.writeUTF(Constant.ALL_MSG);
                // 将消息发送到服务端
                out.writeUTF(message);
                out.flush();
            }
        } catch (IOException e) {
            System.out.println("客户端发送群聊消息失败");
            e.printStackTrace();
        }
    }

    // 打开私聊窗口
    private void openPrivateChatWindow() {
        String selectedUser = userList.getSelectedValue();
        if (selectedUser == null) {
            JOptionPane.showMessageDialog(this, "请选择一个用户进行私聊。", "提示", JOptionPane.WARNING_MESSAGE);
            return;
        } else if (selectedUser.equals(AppContext.getInstance().getUsername())) {
            JOptionPane.showMessageDialog(this, "私聊不能选择自己，请重新选择！", "提示", JOptionPane.WARNING_MESSAGE);
            return;
        }

        privateChatPanel = new PrivateChatWindow(selectedUser);
    }

    // 更新在线用户列表
    public void updateOnLineUserList(List<String> onLineUsers) {
        // 每次更新都要把之前的清除掉
        userModel.clear();
        for (String onLineUser : onLineUsers) {
            userModel.addElement(onLineUser);
        }
    }

    // 获取群发消息，并展示在聊天框中
    public void showMsgToAll(String msg) {
        chatArea.append(msg + "\r\n");
    }

    /**
     * @param fromUser 发送者
     * @param toUser   接收者
     * @param message  消息体
     */
    public void onServerMessageReceived(String fromUser, String toUser, String message) {
        String currentUsername = AppContext.getInstance().getUsername();
        // 判断当前用户是不是目标接收者
        if (currentUsername.equals(toUser)) {
            // 如果已经有私聊窗口打开，则直接更新它
            if (PrivateChatWindow.isOpenFor(fromUser)) {
                SwingUtilities.invokeLater(() -> privateChatPanel.showMsgToPersonal(fromUser, message));
            } else {
                // 否则缓存消息，并通知
                PrivateMessageCache.getInstance().addUnreadMessage(fromUser, new PrivateMessage(fromUser, message));
                PrivateMessageNotifier.notifyNewMessage(this, fromUser);
            }
        }
    }
}